#ifndef __SEARCH_ENGINE_H__
#define __SEARCH_ENGINE_H__

#include "TcpServer.h"
#include "TcpConnection.h"
#include "ProtocolParser.h"
#include "ThreadPool.h"
#include "KeyRecommander.h" 
#include "../Web_Search/WebPageSearcher.h"
#include "../../include/nlohmann/json.hpp"
#include "MyTask.h"
#include <cstdlib>
#include <iostream>
#include <string>
#include <utility>

using std::cout;
using std::endl;
using std::pair;
using std::string;
using json = nlohmann::json;

// 服务器开启器
class SearchEngineServer{
public:
    SearchEngineServer(size_t threadNum, size_t queSize, const string &ip, unsigned short port)
        : _pool(threadNum, queSize)
        , _server(ip, port)
        , _manager(threadNum){}

    ~SearchEngineServer(){}

    // 某一个功能
    void start(){
        _pool.start(); 

        using namespace std::placeholders;
        _server.setAllCallback(std::bind(&SearchEngineServer::onConnection, this, _1), 
                               std::bind(&SearchEngineServer::onMessage, this, _1), 
                               std::bind(&SearchEngineServer::onClose, this, _1));
       
        _server.start();
    }

   
    void stop(){
        _pool.stop();
        _server.stop();
    }

    
    // 连接建立
    void onConnection(const TcpConnectionPtr &con){
        cout << con->toString() << " has connected!!!" << endl;
    }


    // 接收消息
    void onMessage(const TcpConnectionPtr &con){
        string msg = con->receive(); // 接收 msg
        //  msg 解析
        onParse(msg, _parseResult);
        MyTask task(con, _parseResult); // 创建任务对象
        
        // 执行 push 操作, 将 task 放在任务队列里面
        if(_parseResult.first == 1){ // 执行关键字查询模块
            _pool.addTask(std::bind(&MyTask::process, task, (void*)&_keyWordCommander, _manager));
        }
        else{ // 执行网页查询模块
            _pool.addTask(std::bind(&MyTask::process, task , (void*)&_webPageSearcher, _manager));
        }
    }
   

    void onClose(const TcpConnectionPtr &con){
        cout << con->toString() << " has closed!!!" << endl;
    }

    
    // 解析数据
    void onParse(const string msg, pair<int, string> & result){
        result = _protocolParser.doParse(msg); // 获得消息类型和消息内容
        cout << ">>recv from client msg = " << _parseResult.first << endl; 
        cout << ">>recv from client msg = " << _parseResult.second << endl; 
    }

private:
    pair<int, string> _parseResult;
    ThreadPool _pool;
    TcpServer _server;
    ProtocolParser _protocolParser;
    KeyRecommander _keyWordCommander;
    WebPageSearcher _webPageSearcher;
    LRUmanager _manager;
};

#endif
